﻿using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using VideoConfig;
using IConfig;
using IPlayer;
using System.Reflection;
using VideoFile;
using System.Threading;

namespace Player
{
    /// <summary>
    /// 播放器基类
    /// </summary>
    public partial class PlayerBase : UserControl, IPlayerBase
    {
        #region 保护属性
        IConfigInfo configInfo;
        /// <summary>
        /// 设备配置模块
        /// </summary>
        protected IConfigInfo ConfigInfo { get { return configInfo; } }

        IPlayerSDK player;
        /// <summary>
        /// 播放器模块
        /// </summary>
        protected IPlayerSDK Player { get { return this.player; } }

        #endregion

        #region 构造函数
        /// <summary>
        /// 构造函数
        /// </summary>
        public PlayerBase()
        {
            InitializeComponent();
        }

        #endregion

        #region 静态方法
        /// <summary>
        /// 获取区域设备列表
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, List<string>> GetAreaDeviceList()
        {
            return FileConfigReader.SingleConfig.GetAreaDeviceList();
        }

        

        /// <summary>
        /// 获取指定日期的录像文件
        /// </summary>
        /// <param name="area">区域名称</param>
        /// <param name="device">设备名称</param>
        /// <param name="time">年月日</param>
        /// <returns></returns>
        public static DateTime[] GetAreaDeviceDateRecords(string area, string device, DateTime time)
        {
            //获取根目录
            string record = FileConfigReader.SingleConfig[area, device]["record"];

            return FilePath.GetDatePathFileInfo(record, area, device, "mp4", time);
        }
        #endregion

        #region 私有方法
        //动态构建类型
        object CreateType(string assemblyFile, string typename)
        {
            try
            {
                Assembly videoAssembly = Assembly.LoadFrom(assemblyFile);
                Type videoType = videoAssembly.GetType(typename);
                ConstructorInfo videoConstructor = videoType.GetConstructor(new Type[0]);
                return videoConstructor.Invoke(null);
            }
            catch (Exception Ex)
            {
                throw new ApplicationException(string.Format("Load Assembly {0} Type {1} Failed!|Initialize", assemblyFile, typename), Ex);
            }
        }

        void PlayerPaintCall(Graphics graphics)
        {
            OnPlayerPaint(new EventArgsPaint(graphics));
        }

        #endregion

        #region 事件函数
        /// <summary>
        /// 播放器绘图
        /// </summary>
        /// <param name="e">绘图事件参数</param>
        protected virtual void OnPlayerPaint(EventArgsPaint e)
        {
            if (this.PlayerPaint != null) this.PlayerPaint(this, e);
        }

        
        /// <summary>
        /// 窗体消息处理
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            //播放结束
            if (m.Msg == 0x1111)
            {
                this.player.Stop();
                this.Invalidate();
                OnPlayEnd(null);
            }
            base.WndProc(ref m);
        }
        protected virtual void OnPlayEnd(EventArgs e)
        {
            if (this.PlayEnd != null) PlayEnd(this, e);
        }
        #endregion

        #region IPlayerBase 成员
        #region 公有事件
        /// <summary>
        /// 播放结束事件
        /// </summary>
        public event EventHandler PlayEnd;

        /// <summary>
        /// 绘图事件
        /// </summary>
        public event EventHandler<IPlayer.EventArgsPaint> PlayerPaint;

        /// <summary>
        /// 解码事件
        /// </summary>
        public event EventHandler<IPlayer.EventArgsDecode> Decode;
        #endregion

        #region 录像属性
        DateTime startTime = new DateTime();
        /// <summary>
        /// 起始时间
        /// </summary>
        public DateTime StartTime
        {
            get { return startTime; }
        }

        string area = string.Empty;
        /// <summary>
        /// 录像区域名称
        /// </summary>
        public string Area
        {
            get { return this.area; }
        }

        string device = string.Empty;
        /// <summary>
        /// 录像设备名称
        /// </summary>
        public string Device
        {
            get { return this.device; }
        }

        /// <summary>
        /// 总时长（秒）
        /// </summary>
        public TimeSpan TotalTime
        {
            get
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    return new TimeSpan((long)this.player.GetFileTime() * 10000000);
                else
                    return new TimeSpan();
            }
        }

        /// <summary>
        /// 总帧数
        /// </summary>
        public uint TotalFrame
        {
            get
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    return this.player.GetTotalFrames();
                else
                    return 0;
            }
        }

        /// <summary>
        /// 帧率
        /// </summary>
        public uint FrameRate
        {
            get
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    return this.player.GetFrameRate();
                else
                    return 0;
            }
        }

        /// <summary>
        /// 帧大小,即帧图像的宽度和高度
        /// </summary>
        public Size FrameSize
        {
            get
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    return new Size(this.player.Width, this.player.Height);
                else
                    return new Size();
            }
        }
        #endregion

        #region 播放属性
        /// <summary>
        /// 播放指针相对位置，范围：0-100%
        /// </summary>
        [Browsable(false)]
        public float PlayPosition
        {
            get
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    return this.player.GetPlayPos();
                else
                    return 0f;
            }
            set
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay
                    && value <= 1 && value >= 0)
                {
                    this.player.SetPlayPos(value);
                }
            }
        }

        /// <summary>
        /// 当前播放时间，单位：毫秒
        /// </summary>
        [Browsable(false)]
        public TimeSpan PlayedTime
        {
            get
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    return new TimeSpan(this.player.GetPlayedTime() * 10000);
                else return new TimeSpan();
            }
            set
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay
                    && value < new TimeSpan(this.player.GetFileTime() * 10000000))
                    this.player.SetPlayedTime(Convert.ToUInt32(value.Ticks / 10000));
            }
        }

        /// <summary>
        /// 当前帧序号
        /// </summary>
        [Browsable(false)]
        public uint FrameNumber
        {
            get
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    return this.player.GetFrameNumber();
                else return 0;
            }
            set
            {
                if (this.player != null
                    && this.player.OpenState == OpenStateEnum.FilePlay)
                    this.player.SetFrameNumber(value);
            }
        }

        /// <summary>
        /// 播放速度，取值区间：[-4,4]，大于0快放，小于0慢放，等于0正常
        /// </summary>
        [Browsable(false)]
        public int Speed
        {
            get
            {
                if (this.player == null) return 0;

                return this.player.PlaySpeed;
            }
        }
        #endregion

        #region 公有方法
        /// <summary>
        /// 根据区域名和设备名打开这个设备在参数time时间所录的录像文件
        /// </summary>
        /// <param name="area">区域名</param>
        /// <param name="device">设备名</param>
        /// <param name="time">时间</param>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Open(string area, string device, DateTime time)
        {
            if (this.player != null)
            {
                if (this.player.OpenState != OpenStateEnum.Close)
                {
                    this.player.Close();
                }

                if (this.area != area || this.device != device)
                {
                    this.player = null;//如果设备发生改变，则需重新创建Player
                }

                //this.Invalidate();//刷新
            }

            if (this.player == null)
            {
                //获取配置信息
                this.configInfo = FileConfigReader.SingleConfig[area, device];

                if (this.configInfo == null)
                    throw new ApplicationException(string.Format("Get area {0} device {1} config failed!|Initialize", area, device));

                //动态加载播放模块
                this.player = this.CreateType(configInfo["PlayerFile"], configInfo["PlayerType"]) as IPlayer.IPlayerSDK;
                //添加绘图委托
                this.player.PaintCallback = new PaintCallback(this.PlayerPaintCall);

            }

            //获取录像文件全路径
            string file = FilePath.GetDatePathTimeFile(this.configInfo["record"], area, device, time, "mp4");

            if (!File.Exists(file)) return false;

            if (this.player.Open(file, this.Handle))
            {
                this.area = area;
                this.device = device;
                this.startTime = time;//录像起始时间
                return true;
            }
            else
                return false;
        }

        /// <summary>
        /// 关闭播放的录像文件
        /// </summary>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Close()
        {
            if (this.player == null) return false;

            if (this.player.OpenState == OpenStateEnum.FilePlay)
            {
                this.player.Close();

                this.player = null;
            }

            return true;
        }

        /// <summary>
        /// 播放打开的录像文件
        /// </summary>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Play()
        {
            if (this.player == null) return false;

            if (this.player.PlayState != PlayStateEnum.Play)
                return this.player.Play();
            else return true;
        }

        /// <summary>
        /// 停止播放
        /// </summary>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Stop()
        {
            if (this.player == null) return false;

            if (this.player.PlayState != PlayStateEnum.Other
                || this.player.PlayState != PlayStateEnum.Stop)
            {
                bool stop = this.player.Stop();
                //this.Invalidate();
                return stop;
            }
            else return true;
        }

        /// <summary>
        /// 暂停播放
        /// </summary>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Pause()
        {
            if (this.player == null) return false;

            if (this.player.PlayState == PlayStateEnum.Play)
                return this.player.Pause();
            else return true;
        }

        /// <summary>
        /// 恢复播放
        /// </summary>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Continue()
        {
            if (this.player == null) return false;

            if (this.player.PlayState == PlayStateEnum.Pause)
                return this.player.Continue();
            else return true;
        }

        /// <summary>
        /// 快放
        /// </summary>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Fast()
        {
            if (this.player == null) return false;

            if (this.player.PlayState == PlayStateEnum.Play)
                return this.player.Fast();
            else return true;
        }

        /// <summary>
        /// 慢放
        /// </summary>
        /// <returns>true表示成功，false表示失败</returns>
        public bool Slow()
        {
            if (this.player == null) return false;

            if (this.player.PlayState == PlayStateEnum.Play)
                return this.player.Slow();
            else return true;
        }
        #endregion
        #endregion
    }
}
